const { Service } = require('egg');
const dayjs = require('dayjs');
const myDate = require('../utils/myDate');

class ExamService extends Service {
  async me(token) {
    const userInfo = this.app.jwt.decode(token);
    if (!userInfo) {
      return false;
    }
    const user = await this.app.mysql.get('user', { id: userInfo.id });
    const examData = await this.ctx.service.exam.getExam(userInfo.examId);
    if (!user) {
      return {
        state: false,
        msg: '用户不存在',
      };
    }
    return {
      state: true,
      data: {
        userInfo: {
          id: user.id,
          name: user.name,
        },
        exam: examData.exam,
      },
    };
  }

  async getToken(email, userId, key) {
    const isExit = await this.app.mysql.get('user', { email, id: userId });
    if (!isExit) {
      return {
        state: false,
        msg: '用户不存在',
      };
    }
    const isExamExit = await this.app.mysql.get('exam_user', { user_id: userId, token: key });
    if (!isExamExit) {
      return {
        state: false,
        msg: '考试不存在',
      };
    }
    const token = this.app.jwt.sign({
      id: userId,
      examId: isExamExit.exam_id,
    }, this.app.config.jwt.secret);
    return {
      state: true,
      data: {
        token: `Bearer ${token}`,
      },
    };
  }

  async getExam(examId) {
    const res = await this.app.mysql.get('exam', { id: examId });
    const token = this.ctx.request.header.authorization?.slice(7);
    const userInfo = this.app.jwt.decode(token);
    const test = await this.app.mysql.get('exam_user', { exam_id: examId, user_id: userInfo.id });
    if (res) {
      return {
        id: res.id,
        name: res.name,
        begin: res.begin,
        end: res.end,
        duration: res.duration,
        isSubmitSignature: test.signature ? 1 : 0,
        signature: test.signature,
        is_limit_jump: res.is_limit_jump,
        face_recording: res.face_recording,
        limit_jump_times: res.limit_jump_times,
        screen_recording: res.screen_recording,
      };
    }
    return false;
  }

  async begin(userId, examId) {
    const test = await this.app.mysql.get('exam_user', { exam_id: examId, user_id: userId });
    if (test.is_submit) {
      return {
        state: false,
        msg: '考试已提交',
      };
    }
    if (test.begin_time) {
      return {
        state: true,
      };
    }
    const update = await this.app.mysql.update('exam_user', { begin_time: myDate.getNowDate() }, { where: { exam_id: examId, user_id: userId } });
    if (update.affectedRows) {
      return {
        state: true,
      };
    }
    return {
      state: false,
      msg: '考试开始失败',
    };
  }

  async checkConfig(userId, examId) {
    const res = await this.app.mysql.get('exam', { id: examId });
    const test = await this.app.mysql.get('exam_user', { exam_id: examId, user_id: userId });
    if (res) {
      return {
        begin: res.begin,
        end: res.end,
        duration: res.duration,
        begin_time: test.begin_time,
        is_submit: test.is_submit,
        is_dirty: test.is_dirty,
        isSubmitSignature: test.signature ? 1 : 0,
        is_limit_jump: res.is_limit_jump,
        limit_jump_times: res.limit_jump_times,
        jump_times: test.jump_times,
        face_recording: res.face_recording,
        screen_recording: res.screen_recording,
      };
    }
    return false;
  }

  async uploadSignature(signatureBase64) {
    const token = this.ctx.request.header.authorization?.slice(7);
    const userInfo = this.app.jwt.decode(token);
    const updateRes = await this.app.mysql.query('UPDATE exam_user SET signature = ? WHERE user_id = ?', [ signatureBase64, userInfo.id ]);
    if (updateRes.affectedRows) {
      return true;
    }
    return false;
  }

  async getExamPaper(userId, examId) {
    const usedExampaper = await this.app.mysql.get('exam_user', { exam_id: examId, user_id: userId });
    if (!usedExampaper.signature) {
      return {
        state: false,
        msg: '请先签名',
      };
    }
    const begin = dayjs(usedExampaper.begin);
    const end = dayjs(usedExampaper.end);
    const now = dayjs();
    if (now.isBefore(begin)) {
      return {
        state: false,
        msg: '考试时间未到',
      };
    }
    if (now.isAfter(end)) {
      return {
        state: false,
        msg: '考试已结束',
      };
    }
    const res = await this.app.mysql.query('SELECT *  FROM exam_paper_link epl LEFT JOIN exam_paper ep ON epl.paper_id = ep.id WHERE epl.exam_id = ?', [ examId ]);
    if (!res) {
      return {
        state: false,
        msg: '考试试卷不存在',
      };
    }
    if (res.length === 1) {
      await this.app.mysql.query('UPDATE exam_user SET used_paper_id =? WHERE exam_id =? AND user_id =?', [ res[0].id, examId, userId ]);
      delete res[0].content;
      return {
        state: true,
        data: res[0],
      };
    } else if (res.length > 1) {
      if (usedExampaper.used_paper_id) {
        const usedPaper = res.find(item => item.id === usedExampaper.used_paper_id);
        delete usedPaper.content;
        return {
          state: true,
          data: usedPaper,
        };
      }
      const randomPaper = res[Math.floor(Math.random() * res.length)];
      await this.app.mysql.query('UPDATE exam_user SET used_paper_id =? WHERE exam_id =? AND user_id =?', [ randomPaper.id, examId, userId ]);
      delete randomPaper.content;
      return {
        state: true,
        data: randomPaper,
      };
    }
  }


  async submitExamPaper(examPaper, userId, examId) {
    const exam = await this.app.mysql.get('exam', { id: examId });
    // 笔试开始之前提交 标记为脏试卷
    if (dayjs().isBefore(dayjs(exam.begin))) {
      await this.app.mysql.update('exam_user', { is_dirty: 1 }, { where: { exam_id: examId, user_id: userId } });
      return {
        state: false,
        msg: '考试未开始',
      };
    }
    // 笔试结束后不可提交
    if (dayjs().isAfter(dayjs(exam.end))) {
      return {
        state: false,
        msg: '考试已结束',
      };
    }
    const test = await this.app.mysql.get('exam_user', { exam_id: examId, user_id: userId });
    // 不可重复提交
    if (Number(test.is_submit) === 1) {
      return {
        state: false,
        msg: '已提交',
      };
    }

    // 提交 更新答案
    const updateExamUser = await this.app.mysql.update('exam_user', { is_submit: 1, submit_res: JSON.stringify(examPaper), submit_time: myDate.getNowDate() }, { where: { exam_id: examId, user_id: userId } });
    const rb = await this.app.rabbitmq.sendMessage(JSON.stringify({ exam_id: examId, user_id: userId }));
    if (updateExamUser.affectedRows && rb) {
      return {
        state: true,
        msg: '提交成功',
      };
    }
    return {
      state: false,
      msg: '提交失败',
    };
  }

  async sendJumpMsg(userId, examId) {
    const test = await this.app.mysql.get('exam_user', { exam_id: examId, user_id: userId });
    let times = 0;
    if (test.jump_times) {
      times = test.jump_times;
    }
    const update = await this.app.mysql.update('exam_user', { jump_times: times + 1 }, { where: { exam_id: examId, user_id: userId } });
    const exam = await this.app.mysql.get('exam', { id: examId });
    if (times >= exam.limit_jump_times) {
      await this.app.mysql.update('exam_user', { is_dirty: 1 }, { where: { exam_id: examId, user_id: userId } });
    }
    if (update.affectedRows) {
      return true;
    }
    return false;
  }
}

module.exports = ExamService;
